/**
 * TMan.java
 * ************************** 
 * @date May 5, 2011
 * @author Michele Tamburini
 * 
 * **************************
 */
package gossipServices.bootstraping.tman;

import gossipServices.basic.nodeDescriptors.GeneralNodeDescriptor;
import gossipServices.basic.nodeDescriptors.NodeDescriptor;
import gossipServices.basic.view.PartialView;
import gossipServices.basic.view.PartialView.PEER_SELECTION_ENUM;
import gossipServices.gossipMessages.TManMessage;
import gossipServices.gossipThread.GossipBasedProtocol;
import gossipServices.pss.PeerSamplingServiceAPI;

/**
 * Description: 
 * TMan is a gossip algorithm able to build an overlay among nodes.
 * It relies on a {@link PeerSamplingServiceAPI} which will provide a sample
 * of the nodes to TMan.
 * 
 * Referring to the paper:
 * "T-Man: Gossip-based fast overlay topology construction"
 * M. Jelasity, A. Montresor, O. Babaoglu, 2009, Computer Networks
 *
 */
public class TMan extends GossipBasedProtocol
	implements TManService {
	
	protected TManNetworkManager tmanNm;
	protected String subcloudID;
	
	
	/**
	 * @param cyclelength
	 * @param view
	 * @param pss
	 * @param tmanNm
	 * @param local
	 * @param rankingMet
	 * @param m
	 * @param psi
	 */
	public TMan(long cycleLengthMsec, PartialView initView, PeerSamplingServiceAPI pss,
			TManNetworkManager tmanNm, NodeDescriptor localNodeDescriptor,
			TManRankingMethod rankingMet, int messageSize, int psi, int tabuListSize, 
			String subcloudID) {
		
		super(new TManActiveThread("TManActive-"+subcloudID, cycleLengthMsec, initView,
				pss, tmanNm, localNodeDescriptor, rankingMet, messageSize, psi, tabuListSize, subcloudID),
			new TManPassiveThread("TManPassive-"+subcloudID, cycleLengthMsec, initView,
				pss, tmanNm, localNodeDescriptor, rankingMet, messageSize, psi, tabuListSize, subcloudID));
		/*
		 * TMAN VIEW:
		 * Note that the view is always re-created in each cycle because of the
		 * rank() method
		 * 
		 */
		this.subcloudID = subcloudID;
		this.tmanNm = tmanNm;
	}


	// NOTE: in future release we may want to relax this
	// condition and provide a completely non static access...
	@Override
	public PartialView getOverlayNeighbors() {
		return ((TManMiddleware) passiveThread).getView();
	}


	@Override
	public Class<?> getServiceClass() {
		return TManService.class;
	}


	@Override
	public String getSubcloudID() {
		return subcloudID;
	}


	@Override
	public boolean stopTMan() {
		this.stopGossipProtocol();
		return true;
	}


	@Override
	public boolean restartTMan(PartialView newView) {
		// try to wake up the TMan thread by the sending of an empty message
		NodeDescriptor dest = newView.selectPeer(PEER_SELECTION_ENUM.rand);
		NodeDescriptor local = new GeneralNodeDescriptor(tmanNm.getNodeName());
		TManMessage msg = new TManMessage(local, dest, newView, 
				TManActiveThread.class, subcloudID);
		System.out.println("Restarting TMan with message: "+msg);
		tmanNm.send(msg, local);
		return true;
	}


	@Override
	public boolean startTMan() {
		this.start();
		return true;
	}

}
